using MicroMsg.Common.Utils;
using MicroMsg.Scene;
using System;
using System.Collections.Generic;
using System.Windows;
namespace MicroMsg.Storage
{
	public class StorageSynchro<T, TKey> where T : StorageItem
	{
		private const string TAG = "DataSynchro";
		private StorageTable<T, TKey> storage;
		private Func<T, TKey> getKey;
		private object lockSaveChange = new object();
		private List<DataChange> pendingList = new List<DataChange>();
		private Dictionary<TKey, DataChange> mapPending = new Dictionary<TKey, DataChange>();
		private int requestCount;
		public StorageSynchro(StorageTable<T, TKey> storageTable_0, Func<T, TKey> func_0)
		{
			this.storage = storageTable_0;
			this.getKey = func_0;
		}
		public int setFlushCompleteHandler(Action Flushcomplete)
		{
			if (Flushcomplete == null)
			{
				return 0;
			}
			ServiceCenter.asyncExec(delegate
			{
				Deployment.get_Current().get_Dispatcher().BeginInvoke(delegate
				{
					Log.smethod_5("DataSynchro", "do Flushcomplete  callback ");
					Flushcomplete.Invoke();
				});
			});
			return 1;
		}
		private bool combineOper(DataOper opCur, object data)
		{
			TKey tKey = this.getKey.Invoke(data as T);
			if (!this.mapPending.ContainsKey(tKey))
			{
				return false;
			}
			DataOper dataOper_ = this.mapPending.get_Item(tKey).dataOper_0;
			if (dataOper_ != DataOper.const_0)
			{
				if (dataOper_ != DataOper.modify)
				{
					if (dataOper_ != DataOper.const_1)
					{
						goto IL_CA;
					}
					switch (opCur)
					{
					case DataOper.const_0:
						this.mapPending.get_Item(tKey).dataOper_0 = DataOper.modify;
						this.mapPending.get_Item(tKey).data = data;
						Log.smethod_1("DataSynchro", "op combine del + add = modify");
						return true;
					case DataOper.const_1:
						Log.smethod_1("DataSynchro", " op Conflict opdel + opdel");
						return false;
					case DataOper.modify:
						Log.smethod_1("DataSynchro", " op Conflict opdel + opModify");
						return false;
					default:
						goto IL_CA;
					}
				}
			}
			switch (opCur)
			{
			case DataOper.const_0:
			case DataOper.modify:
				this.mapPending.get_Item(tKey).data = data;
				return true;
			case DataOper.const_1:
				this.pendingList.Remove(this.mapPending.get_Item(tKey));
				this.mapPending.Remove(tKey);
				return dataOper_ == DataOper.const_0;
			default:
				IL_CA:
				Log.smethod_1("DataSynchro", "error opCur=" + opCur);
				return false;
			}
		}
		public void method_0(DataOper dataOper_0, object data)
		{
			lock (this.pendingList)
			{
				this.requestCount++;
				if (!this.combineOper(dataOper_0, data))
				{
					DataChange dataChange = new DataChange(dataOper_0, data);
					this.pendingList.Add(dataChange);
					TKey tKey = this.getKey.Invoke(data as T);
					this.mapPending.set_Item(tKey, dataChange);
					if (this.requestCount == 1)
					{
						Deployment.get_Current().get_Dispatcher().BeginInvoke(delegate
						{
							this.doSaveChangeAsync();
						});
					}
				}
			}
		}
		private void doSaveChangeAsync()
		{
			ServiceCenter.asyncExec(delegate
			{
				this.doSaveChange();
			});
		}
		public void doSaveChange()
		{
			List<DataChange> list = new List<DataChange>();
			lock (this.lockSaveChange)
			{
				lock (this.pendingList)
				{
					if (this.pendingList.get_Count() <= 0)
					{
						return;
					}
					this.requestCount = 0;
					list.AddRange(this.pendingList);
					this.pendingList.Clear();
					this.mapPending.Clear();
				}
				this.storage.dataChangeResponse(list);
				list.Clear();
			}
		}
	}
}
